﻿'Imports System.Collections

' ''' <summary>
' ''' This is a game component that implements IUpdateable.
' ''' </summary>

'Public Class ThreeDElements
'    Inherits Microsoft.Xna.Framework.GameComponent
'    Public blah As New Collision(MyBase.Game)
'    Public Position As Vector2
'    Public Terrain As Model
'    Public TerrainTransforms As Matrix
'    Public pickedModelName As String
'    Public pickedTriangle As VertexPositionColor() = {New VertexPositionColor(Vector3.Zero, Color.Magenta), New VertexPositionColor(Vector3.Zero, Color.Magenta), New VertexPositionColor(Vector3.Zero, Color.Magenta)}
'    Public lineEffect As BasicEffect
'    Public WireFrame As New RasterizerState() With {.FillMode = FillMode.WireFrame, .CullMode = CullMode.None}
'    Private models As Model() = New Model(ModelFilenames.Length - 1) {}
'    Private modelAbsoluteBoneTransforms As Matrix()() = New Matrix(ModelFilenames.Length - 1)() {}
'    Private modelWorldTransforms As Matrix() = New Matrix(ModelFilenames.Length - 1) {}
'    Shared ReadOnly ModelFilenames As String() = {"Terrain"}
'    Private insideBoundingSpheres As New List(Of String)()
'    Public Spritefont As SpriteFont

'    Public Sub New(ByVal game As DanoQuest)
'        MyBase.New(game)
'        game.Components.Add(Me)
'        Terrain = game.Content.Load(Of Model)("Terrain")
'        For Each mesh As ModelMesh In Terrain.Meshes
'            For Each effect As BasicEffect In mesh.Effects
'                effect.EnableDefaultLighting()  'Set the default lighting flag, doe snot have to be set in every draw loop , so it is set here
'            Next
'        Next
'        For i As Integer = 0 To modelWorldTransforms.Length - 1
'            Dim x As Single = i - modelWorldTransforms.Length / 2
'            modelWorldTransforms(i) = Matrix.CreateTranslation(New Vector3(0, 0, 0))
'        Next
'        For i As Integer = 0 To ModelFilenames.Length - 1
'            models(i) = game.Content.Load(Of Model)(ModelFilenames(i))
'            modelAbsoluteBoneTransforms(i) = New Matrix(models(i).Bones.Count - 1) {}
'            models(i).CopyAbsoluteBoneTransformsTo(modelAbsoluteBoneTransforms(i))
'        Next
'        Spritefont = game.Content.Load(Of SpriteFont)("Spritefont1")
'        lineEffect = New BasicEffect(game.graphics.GraphicsDevice)
'        lineEffect.VertexColorEnabled = True
'    End Sub

'    Public Function RayIntersectsModel(ray As Ray, model As Model, modelTransform As Matrix, ByRef insideBoundingSphere As Boolean, ByRef vertex1 As Vector3, ByRef vertex2 As Vector3, ByRef vertex3 As Vector3) As System.Nullable(Of Single)
'        vertex1 = InlineAssignHelper(vertex2, InlineAssignHelper(vertex3, Vector3.Zero))
'        Dim inverseTransform As Matrix = Matrix.Invert(modelTransform)
'        ray.Position = Vector3.Transform(ray.Position, inverseTransform)
'        ray.Direction = Vector3.TransformNormal(ray.Direction, inverseTransform)
'        Dim tagData As Dictionary(Of String, Object) = DirectCast(model.Tag, Dictionary(Of String, Object))
'        If tagData Is Nothing Then
'            Throw New InvalidOperationException("Model.Tag is not set correctly. Make sure your model " + "was built using the custom TrianglePickingProcessor.")
'        End If
'        Dim boundingSphere As BoundingSphere = DirectCast(tagData("BoundingSphere"), BoundingSphere)
'        If boundingSphere.Intersects(ray) Is Nothing Then
'            insideBoundingSphere = False
'            Return Nothing
'        Else
'            insideBoundingSphere = True
'            Dim closestIntersection As System.Nullable(Of Single) = Nothing
'            Dim vertices As Vector3() = DirectCast(tagData("Vertices"), Vector3())
'            For i As Integer = 0 To vertices.Length - 1 Step 3
'                Dim intersection As System.Nullable(Of Single)
'                RayIntersectsTriangle(ray, vertices(i), vertices(i + 1), vertices(i + 2), intersection)
'                If intersection IsNot Nothing Then
'                    If (closestIntersection Is Nothing) Or (intersection < closestIntersection) Then
'                        closestIntersection = intersection
'                        Vector3.Transform(vertices(i), modelTransform, vertex1)
'                        Vector3.Transform(vertices(i + 1), modelTransform, vertex2)
'                        Vector3.Transform(vertices(i + 2), modelTransform, vertex3)
'                    End If
'                End If
'            Next
'            Return closestIntersection
'        End If
'    End Function

'    Public test As Single = 0

'    Public Sub RayIntersectsTriangle(ByRef ray As Ray, ByRef vertex1 As Vector3, ByRef vertex2 As Vector3, ByRef vertex3 As Vector3, ByRef result As System.Nullable(Of Single))
'        Dim edge1 As Vector3, edge2 As Vector3
'        Vector3.Subtract(vertex2, vertex1, edge1)
'        Vector3.Subtract(vertex3, vertex1, edge2)
'        Dim directionCrossEdge2 As Vector3
'        Vector3.Cross(ray.Direction, edge2, directionCrossEdge2)
'        Dim determinant As Single
'        Vector3.Dot(edge1, directionCrossEdge2, determinant)
'        If (determinant > -Single.Epsilon) And (determinant < Single.Epsilon) Then
'            result = Nothing
'            Return
'        End If
'        Dim inverseDeterminant As Single = 1.0F / determinant
'        Dim distanceVector As Vector3
'        Vector3.Subtract(ray.Position, vertex1, distanceVector)
'        Dim triangleU As Single
'        Vector3.Dot(distanceVector, directionCrossEdge2, triangleU)
'        triangleU = triangleU * inverseDeterminant
'        If triangleU < 0 Or triangleU > 1 Then
'            result = Nothing
'            Return
'        End If
'        Dim distanceCrossEdge1 As Vector3
'        Vector3.Cross(distanceVector, edge1, distanceCrossEdge1)
'        Dim triangleV As Single
'        Vector3.Dot(ray.Direction, distanceCrossEdge1, triangleV)
'        triangleV = triangleV * inverseDeterminant
'        If triangleV < 0 Or (triangleU + triangleV) > 1 Then
'            result = Nothing
'            Return
'        End If
'        Dim rayDistance As Single
'        Vector3.Dot(edge2, distanceCrossEdge1, rayDistance)
'        rayDistance = rayDistance * inverseDeterminant
'        test = rayDistance.ToString
'        If rayDistance < 0 Then
'            result = Nothing
'            Return
'        End If
'        result = rayDistance
'    End Sub

'    Public Sub updatepicking()
'        Dim cursorRay As Ray = New Ray(Game.Components.OfType(Of Camera).ToList.Item(0).CameraPosition, New Vector3(0, -1, 0)) 'Collision checks with camera and top of mesh 
'        insideBoundingSpheres.Clear()
'        pickedModelName = Nothing
'        Dim closestIntersection As Single = Single.MaxValue
'        For i As Integer = 0 To models.Length - 1
'            Dim insideBoundingSphere As Boolean
'            Dim vertex1 As Vector3, vertex2 As Vector3, vertex3 As Vector3
'            Dim intersection As System.Nullable(Of Single) = RayIntersectsModel(cursorRay, models(i), modelWorldTransforms(i), insideBoundingSphere, vertex1, vertex2, vertex3)
'            If insideBoundingSphere Then
'                insideBoundingSpheres.Add(ModelFilenames(i))
'            End If
'            If intersection IsNot Nothing Then
'                If intersection < closestIntersection Then
'                    closestIntersection = intersection.Value
'                    pickedModelName = ModelFilenames(i)
'                    pickedTriangle(0).Position = vertex1
'                    pickedTriangle(1).Position = vertex2
'                    pickedTriangle(2).Position = vertex3
'                End If
'            End If
'        Next
'    End Sub

'    Private Sub DrawPickedTriangle()
'        If pickedModelName IsNot Nothing Then
'            Dim device As GraphicsDevice = MyBase.Game.GraphicsDevice
'            device.RasterizerState = WireFrame
'            device.DepthStencilState = DepthStencilState.None
'            lineEffect.Projection = Game.Components.OfType(Of Camera).ToList.Item(0).ProjectionMatrix
'            lineEffect.View = Game.Components.OfType(Of Camera).ToList.Item(0).ViewMatrix
'            lineEffect.CurrentTechnique.Passes(0).Apply()
'            device.DrawUserPrimitives(PrimitiveType.TriangleList, pickedTriangle, 0, 1)
'            device.RasterizerState = RasterizerState.CullCounterClockwise
'            device.DepthStencilState = DepthStencilState.Default
'        End If
'    End Sub

'    Private Sub DrawText(spritebatch As SpriteBatch)
'        Dim shadowOffset As New Vector2(1, 1)
'        If insideBoundingSpheres.Count > 0 Then
'            Dim text As String = "Inside bounding sphere: " + String.Join(", ", insideBoundingSpheres.ToArray())
'            Dim position As New Vector2(1, 150)
'            SpriteBatch.DrawString(Spritefont, text, position + shadowOffset, Color.Black)
'            SpriteBatch.DrawString(Spritefont, text, position, Color.White)
'        End If
'        If pickedModelName IsNot Nothing Then
'            Dim position As Vector2 = Game.Components.OfType(Of Camera).ToList.Item(0).MousePosition 'Cursor =========!!!!!!!!!!!11=================
'            position.Y += 32
'            position -= Spritefont.MeasureString(pickedModelName) / 2
'            spritebatch.DrawString(Spritefont, pickedModelName, position + shadowOffset, Color.Black)
'            spritebatch.DrawString(Spritefont, pickedModelName, position, Color.White)
'        Else
'            'Game.Components.OfType(Of Camera).ToList.Item(0).CameraPosition.Y += 3
'        End If
'    End Sub

'    ''' <summary>
'    ''' Allows the game component to perform any initialization it needs to before starting
'    ''' to run.  This is where it can query for any required services and load content.
'    ''' </summary>
'    Public Overrides Sub Initialize()
'        ' TODO: Add your initialization code here
'        MyBase.Initialize()
'    End Sub


'    ''' <summary>
'    ''' Allows the game component to update itself.
'    ''' </summary>
'    ''' <param name="gameTime">Provides a snapshot of timing values.</param>
'    Public Overrides Sub Update(ByVal gameTime As GameTime)
'        updatepicking()
'        Try
'            Debug.WriteLine(blah.Distance(New Ray(Game.Components.OfType(Of Camera).ToList.Item(0).CameraPosition, New Vector3(0, -1, 0)), models(0), modelWorldTransforms(0)).ToString)
'        Catch exception As System.Exception
'            Debug.WriteLine(exception.Message)
'        Finally
'        End Try

'        MyBase.Update(gameTime)
'    End Sub

'    Public Sub Draw(spriteBatch As SpriteBatch)
'        MyBase.Game.GraphicsDevice.BlendState = BlendState.Opaque
'        MyBase.Game.GraphicsDevice.DepthStencilState = DepthStencilState.[Default]
'        For i As Integer = 0 To models.Length - 1
'            DrawModel(models(i), modelWorldTransforms(i), modelAbsoluteBoneTransforms(i))
'        Next
'        drawpickedtriangle()
'        DrawText(spriteBatch)
'    End Sub

'    Private Sub DrawModel(ByRef model As Model, ByRef worldTransform As Matrix, ByRef absoluteBoneTransforms As Matrix())
'        For Each mesh As ModelMesh In model.Meshes
'            For Each effect As BasicEffect In mesh.Effects
'                effect.EnableDefaultLighting()
'                effect.PreferPerPixelLighting = True
'                effect.View = Game.Components.OfType(Of Camera).ToList.Item(0).ViewMatrix
'                effect.Projection = Game.Components.OfType(Of Camera).ToList.Item(0).ProjectionMatrix
'                effect.World = absoluteBoneTransforms(mesh.ParentBone.Index) * worldTransform
'            Next
'            mesh.Draw()
'        Next
'    End Sub

'    Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByRef value As T) As T
'        target = value
'        Return value
'    End Function

'    'Private Sub DrawModel(Model As Model, scale As Matrix, location As Vector3)
'    '    Game.Components.OfType(Of Camera).ToList.Item(0).worldmatrix = scale * Matrix.CreateRotationY(MathHelper.Pi) * Matrix.CreateTranslation(location) 'Scale, ?, Location
'    '    Dim modelTransforms(Model.Bones.Count) As Matrix
'    '    Model.CopyAbsoluteBoneTransformsTo(modelTransforms)
'    '    For Each mesh As ModelMesh In Model.Meshes
'    '        For Each effect As BasicEffect In mesh.Effects
'    '            effect.World = modelTransforms(mesh.ParentBone.Index) * Game.Components.OfType(Of Camera).ToList.Item(0).worldmatrix
'    '            effect.View = Game.Components.OfType(Of Camera).ToList.Item(0).ViewMatrix
'    '            effect.Projection = Game.Components.OfType(Of Camera).ToList.Item(0).projectionMatrix
'    '            mesh.Draw()
'    '        Next
'    '    Next
'    'End Sub
'End Class
